package com.jackie.easyble.ui.activities.search

import android.annotation.SuppressLint
import android.bluetooth.le.ScanResult
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.chad.library.adapter4.BaseQuickAdapter
import com.sscl.easyble.BleManager
import com.sscl.easyble.enums.blescan.BleCallbackType
import com.sscl.easyble.enums.blescan.BleMatchMode
import com.sscl.easyble.enums.blescan.BleScanMode
import com.sscl.easyble.enums.blescan.BleScanPhy
import com.sscl.easyble.extensions.getFailMsg
import com.sscl.easyble.extensions.indexOfScanResults
import com.sscl.easyble.interfaces.scans.OnBleScanListener
import com.jackie.easyble.IntentConstants
import com.jackie.easyble.R
import com.jackie.easyble.ui.adapter.SingleConnectDeviceRecyclerAdapter
import com.jackie.easyble.databinding.ActivitySingleDeviceScanBinding
import com.jackie.easyble.ui.activities.connect.single.SingleConnectActivity
import com.jackie.easyble.ui.activities.scanrecordparse.ScanRecordParseActivity
import com.jackie.easyble.ui.dialogs.SetFullMacFilterDialog
import com.jackie.easyble.ui.dialogs.SetFullNameFilterDialog
import com.jackie.easyble.ui.dialogs.SetStartMacFilterDialog
import com.jackie.easyble.ui.dialogs.SetStartNameFilterDialog
import com.sscl.baselibrary.activity.BaseDataBindingAppCompatActivity
import com.sscl.baselibrary.utils.DebugUtil
import com.sscl.baselibrary.utils.DefaultItemDecoration
import com.sscl.baselibrary.utils.ToastUtil
import com.sscl.easyble.enums.blescan.BleNumOfMatches
import java.util.concurrent.TimeUnit

/**
 * 单设备连接-搜索界面
 */
class SingleDeviceScanActivity :
    BaseDataBindingAppCompatActivity<ActivitySingleDeviceScanBinding>() {

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 属性声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /* * * * * * * * * * * * * * * * * * * 常量属性 * * * * * * * * * * * * * * * * * * */

    /**
     * 设备列表适配器
     */
    private val singleConnectDeviceRecyclerAdapter = SingleConnectDeviceRecyclerAdapter()

    /**
     * 设备列表适配器Item点击事件
     */
    private val onItemClickListener =
        BaseQuickAdapter.OnItemClickListener { adapter, view, position ->
            if (BleManager.getScannerInstance().scanning) {
                BleManager.getScannerInstance().stopScan()
            }
            toConnectActivity(adapter.items[position])
        }

    /**
     * 设备列表适配器Item长点击事件
     */
    private val onItemLongClickListener =
        BaseQuickAdapter.OnItemLongClickListener { adapter, view, position ->
            if (BleManager.getScannerInstance().scanning) {
                BleManager.getScannerInstance().stopScan()
            }
            showDeviceOptionDialog(adapter.items[position])
            true
        }

    /**
     * 下拉刷新
     */
    @SuppressLint("MissingPermission")
    private val onRefreshListener = SwipeRefreshLayout.OnRefreshListener {
        if (BleManager.getScannerInstance().scanning) {
            BleManager.getScannerInstance().stopScan()
        }
        while (singleConnectDeviceRecyclerAdapter.items.isNotEmpty()) {
            singleConnectDeviceRecyclerAdapter.removeAt(0)
        }
        BleManager.getScannerInstance().startScan(true)
        binding.refreshLayout.isRefreshing = false
    }

    /**
     * 蓝牙设备搜索回调
     */
    private val onBleScanListener = object : OnBleScanListener {
        override fun onScanFindOneNewDevice(scanResult: ScanResult) {
            DebugUtil.warnOut(tag, "onScanFindOneNewDevice $scanResult")
            singleConnectDeviceRecyclerAdapter.add(scanResult)
        }

        override fun onScanComplete() {
            DebugUtil.warnOut(tag, "onScanComplete")
        }

        override fun onBatchScanResults(results: List<ScanResult>) {
            DebugUtil.warnOut(tag, "onBatchScanResults ${results.size}")
        }

        override fun onScanFailed(errorCode: Int) {
            DebugUtil.warnOut(tag, "onScanFailed ${errorCode.getFailMsg()}")
        }

        override fun onScanResultInfoUpdate(result: ScanResult) {
            super.onScanResultInfoUpdate(result)
            DebugUtil.warnOut(tag, "onScanResultInfoUpdate $result")
            val indexOf = singleConnectDeviceRecyclerAdapter.items.indexOfScanResults(result)
            if (indexOf < 0) return
            singleConnectDeviceRecyclerAdapter[indexOf] = result
        }

        override fun onScanFindOneDevice(scanResult: ScanResult) {
            super.onScanFindOneDevice(scanResult)
            DebugUtil.warnOut(tag, "onScanFindOneDevice $scanResult")
        }
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 实现方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 设置布局
     */
    override fun setLayout(): Int {
        return R.layout.activity_single_device_scan
    }

    /**
     * 标题栏的返回按钮被按下的时候回调此方法
     */
    override fun titleBackClicked(): Boolean {
        return false
    }

    /**
     * 在设置布局之前需要进行的操作
     */
    override fun doBeforeSetLayout() {

    }

    /**
     * 设置DataBinding
     * 可在此处设置binding的viewModel或观察者等操作
     */
    override fun setBinding() {

    }

    /**
     * 在设置布局之后，进行其他操作之前，所需要初始化的数据
     */
    override fun doBeforeInitOthers() {
        setTitleText(R.string.search_device)
    }

    /**
     * 初始化控件数据
     */
    override fun initViewData(savedInstanceState: Bundle?) {
        binding.deviceListRv.layoutManager = LinearLayoutManager(this)
        binding.deviceListRv.addItemDecoration(DefaultItemDecoration.newLine(Color.GRAY))
        binding.deviceListRv.adapter = singleConnectDeviceRecyclerAdapter
    }

    /**
     * 初始化其他数据
     */
    override fun initOtherData() {

    }

    /**
     * 初始化事件
     */
    override fun initEvents() {
        BleManager.getScannerInstance()
            .setOnBleScanListener(onBleScanListener)
        binding.refreshLayout.setOnRefreshListener(onRefreshListener)
        singleConnectDeviceRecyclerAdapter.setOnItemClickListener(onItemClickListener)
        singleConnectDeviceRecyclerAdapter.setOnItemLongClickListener(onItemLongClickListener)
    }

    /**
     * 在最后进行的操作
     */
    override fun doAfterAll() {
        binding.refreshLayout.autoRefresh()
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 重写方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.activity_device_scan, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.set_ble_scan_mode -> {
                showSelectBleScanModeDialog()
            }

            R.id.set_ble_match_mode -> {
                showSelectBleMatchModeDialog()
            }

            R.id.set_ble_num_of_match -> {
                showSelectBleNumOfMatchDialog()
            }

            R.id.set_ble_callback_type -> {
                showSelectBleCallbackTypeDialog()
            }

            R.id.set_ble_report_delay -> {
                showSetBleReportDelayDialog()
            }

            R.id.set_ble_scan_phy -> {
                showSelectBleScanPhyDialog()
            }

            R.id.set_ble_scan_timeout -> {
                showSetBleScanTimeoutDialog()
            }

            R.id.name_filter -> {
                showNameFilterOptionsDialog()
            }

            R.id.mac_address_filter -> {
                showMacAddressFilterOptionsDialog()
            }

            R.id.clear_all_filter -> {
                BleManager.getScannerInstance().clearAllFilters()
                ToastUtil.toastLong(this, R.string.cleared)
            }

            R.id.use_legacy -> {
                showUseLegacyDialog()
            }

            R.id.stop_Scan -> {
                BleManager.getScannerInstance().stopScan()
            }

            else -> {
                return false
            }
        }
        return true
    }

    override fun onDestroy() {
        super.onDestroy()
        BleManager.releaseBleScannerInstance()
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 私有方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 显示BLE扫描模式设置对话框
     */
    private fun showSelectBleScanModeDialog() {
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_scan_mode_dialog_title)
            .setItems(R.array.ble_mode) { _, which ->
                val bleScanMode = BleScanMode.entries[which]
                BleManager.getScannerInstance().setBleScanMode(bleScanMode)
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设备操作选项的对话框
     */
    private fun showDeviceOptionDialog(scanResult: ScanResult) {

        AlertDialog.Builder(this)
            .setTitle(R.string.device_options_dialog_title)
            .setItems(R.array.scanned_device_options) { _, which ->
                when (which) {
                    //连接设备
                    0 -> {
                        toConnectActivity(scanResult)
                    }
                    //查看设备广播包
                    1 -> {
                        toScanRecordParseActivity(scanResult)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示BLE匹配模式对话框
     */
    private fun showSelectBleMatchModeDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            ToastUtil.toastLong(this, R.string.ble_match_mode_not_support_with_low_system_version)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_match_mode_dialog_title)
            .setItems(R.array.ble_match_mode) { _, which ->
                val bleMatchMode = BleMatchMode.entries[which]
                BleManager.getScannerInstance().setBleMatchMode(bleMatchMode)
                DebugUtil.warnOut(TAG, "bleMatchMode $bleMatchMode")
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 每个过滤器使用的硬件数量
     */
    private fun showSelectBleNumOfMatchDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            ToastUtil.toastLong(this, R.string.ble_match_mode_not_support_with_low_system_version)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_num_of_match_match_dialog_title)
            .setItems(R.array.ble_num_of_match) { _, which ->
                val bleNumOfMatch = BleNumOfMatches.entries[which]
                BleManager.getScannerInstance().setBleNumOfMatches(bleNumOfMatch)
                DebugUtil.warnOut(TAG, "bleNumOfMatch $bleNumOfMatch")
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 设置回调类型对话框
     */
    private fun showSelectBleCallbackTypeDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            ToastUtil.toastLong(
                this,
                R.string.ble_callback_type_not_support_with_low_system_version
            )
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_callback_type_dialog_title)
            .setItems(R.array.ble_callback_type) { _, which ->
                val bleCallbackType = BleCallbackType.entries[which]
                BleManager.getScannerInstance().setBleCallbackType(bleCallbackType)
                DebugUtil.warnOut(TAG, "bleCallbackType $bleCallbackType")
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设置扫描反馈延时时间的对话框
     */
    private fun showSetBleReportDelayDialog() {
        val view = View.inflate(this, R.layout.view_ble_report_delay, null)
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_report_delay_dialog_title)
            .setView(view)
            .setPositiveButton(R.string.confirm) { _, _ ->
                val text =
                    view.findViewById<EditText>(R.id.scan_report_delay_et).text.toString().trim()
                if (text.isEmpty()) {
                    ToastUtil.toastLong(this, R.string.data_empty)
                    return@setPositiveButton
                }
                val result = try {
                    text.toLong()
                } catch (e: Exception) {
                    ToastUtil.toastLong(this, R.string.data_invalid)
                    return@setPositiveButton
                }
                DebugUtil.warnOut(TAG, "setReportDelay $result")
                BleManager.getScannerInstance().setReportDelay(result)
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示使用旧版广播包的设置对话框
     */
    private fun showUseLegacyDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            ToastUtil.toastLong(this, R.string.legacy_not_support_with_low_system_version)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.use_legacy_dialog_title)
            .setItems(R.array.booleans) { _, which ->
                when (which) {
                    //是
                    0 -> {
                        BleManager.getScannerInstance().setLegacy(true)
                    }

                    1 -> {
                        BleManager.getScannerInstance().setLegacy(false)
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设置扫描时长的对话框
     */
    private fun showSetBleScanTimeoutDialog() {
        val view = View.inflate(this, R.layout.view_ble_scan_timeout, null)
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_scan_timeout_dialog_title)
            .setView(view)
            .setPositiveButton(R.string.confirm) { _, _ ->
                val text = view.findViewById<EditText>(R.id.scan_timeout_et).text.toString().trim()
                if (text.isEmpty()) {
                    ToastUtil.toastLong(this, R.string.data_empty)
                    return@setPositiveButton
                }
                val result = try {
                    text.toLong()
                } catch (e: Exception) {
                    ToastUtil.toastLong(this, R.string.data_invalid)
                    return@setPositiveButton
                }
                DebugUtil.warnOut(TAG, "setScanTimeout $result")
                BleManager.getScannerInstance().setScanTimeout(result,TimeUnit.MILLISECONDS)
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示设置扫描物理层的对话框
     */
    private fun showSelectBleScanPhyDialog() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            ToastUtil.toastLong(this, R.string.ble_scan_phy_not_support_with_low_system_version)
            return
        }
        AlertDialog.Builder(this)
            .setTitle(R.string.set_ble_scan_phy_dialog_title)
            .setItems(R.array.ble_scan_phy) { _, which ->
                val bleScanPhy = BleScanPhy.entries[which]
                if (bleScanPhy == BleScanPhy.PHY_LE_CODED) {
                    if (!BleManager.isLeCodedPhySupported()) {
                        ToastUtil.toastLong(this, R.string.phy_le_coded_mask_not_support)
                        return@setItems
                    }
                }
                BleManager.getScannerInstance().setBleScanPhy(bleScanPhy)
                DebugUtil.warnOut(TAG, "bleScanPhy $bleScanPhy")
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示名称过滤选项对话框
     */
    private fun showNameFilterOptionsDialog() {
        AlertDialog.Builder(this)
            .setTitle(R.string.name_filter_dialog_title)
            .setItems(R.array.name_filter_items) { _, which ->
                when (which) {
                    //匹配开头
                    0 -> {
                        showSetStartNameFilterNameDialog()
                    }
                    //匹配全名
                    1 -> {
                        showSetFullNameFilterDialog()
                    }

                    else -> {
                        DebugUtil.warnOut(TAG, "未处理的名称过滤条件")
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示MAC地址过滤选项对话框
     */
    private fun showMacAddressFilterOptionsDialog() {
        AlertDialog.Builder(this)
            .setTitle(R.string.mac_address_filter_dialog_title)
            .setItems(R.array.mac_filter_items) { _, which ->
                when (which) {
                    //匹配地址开头
                    0 -> {
                        showSetStartMacFilterNameDialog()
                    }
                    //匹配全地址
                    1 -> {
                        showSetFullMacFilterDialog()
                    }

                    else -> {
                        DebugUtil.warnOut(TAG, "未处理的名称过滤条件")
                    }
                }
            }
            .setNegativeButton(R.string.cancel, null)
            .show()
    }

    /**
     * 显示 设置MAC地址-开头匹配过滤条件 的对话框
     */
    private fun showSetStartMacFilterNameDialog() {
        SetStartMacFilterDialog(this, BleManager.getScannerInstance()).show()
    }

    /**
     * 显示 设置MAC地址-全地址 过滤条件 的对话框
     */
    private fun showSetFullMacFilterDialog() {
        SetFullMacFilterDialog(this, BleManager.getScannerInstance()).show()
    }

    /**
     * 显示 设置开头名称过滤条件 的对话框
     */
    private fun showSetStartNameFilterNameDialog() {
        SetStartNameFilterDialog(this, BleManager.getScannerInstance()).show()
    }

    /**
     * 显示 设置完全匹配名称过滤条件 的对话框
     */
    private fun showSetFullNameFilterDialog() {
        SetFullNameFilterDialog(this, BleManager.getScannerInstance()).show()
    }

    /**
     * 跳转到广播包解析界面
     */
    private fun toScanRecordParseActivity(scanResult: ScanResult) {
        val intent = Intent(this, ScanRecordParseActivity::class.java)
        intent.putExtra(IntentConstants.SCAN_RESULT, scanResult)
        startActivity(intent)
    }

    /**
     * 跳转到广播包解析界面
     */
    private fun toConnectActivity(scanResult: ScanResult) {
        val intent = Intent(this, SingleConnectActivity::class.java)
        intent.putExtra(IntentConstants.SCAN_RESULT, scanResult)
        startActivity(intent)
    }
}